package omq.api;

import java.io.IOException;
import java.rmi.RemoteException;

import javax.xml.rpc.ServiceException;

import junit.framework.TestCase;
import omq.api.logger.OMQLogger;
import omq.exception.OMQPropertiesReaderException;
import omq.utils.OMQPropertiesReader;
import omq.utils.OMQUtils;

public class OMQConnectionTestCase extends TestCase{

	int maxMessagesOnLoop=1500; 
	private String omqUser = null;
	private String omqPassword = null;
	private String omqEmail = null;
	private String omqQueueManager = null;
	private String omqQueue = null;
	private String omqSOAPServer = null;
	private OMQPropertiesReader propertiesReader;
	
	private final String invalidName = "INVALIDINVALID123";
	private final String invalidLongName21Chars = "INVALIDINVALID1234567";
	
	// -------------------------------------------
	// setup environment
	// -------------------------------------------
	protected void setUp() throws Exception {
		super.setUp();
		initEnv(new String[]{});
	}
	
	// ----------------------------------------------------------
	// test case - test successfully expected connection
	// ----------------------------------------------------------
	public void testConnectionSuccess() throws ServiceException, RemoteException
	{
//		OMQConnection con = new OMQConnectionSOAP(omqUser,omqPassword,omqSOAPServer,new OMQQueueManager(omqQueueManager));
		OMQConnection con = OMQConnectionFactory.getConnection(omqUser,omqPassword,omqSOAPServer, new OMQQueueManager(omqQueueManager));
		int rc = con.checkConnection(new OMQQueue(omqQueue));
		OMQLogger.getInstance().info("con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription());
		assertEquals("check connection failed on error code "+rc+" error description "+con.getLastErrorDescription(),0,rc);
	}

	public void testConnectionSuccessWithDefaultSOAPServer() throws ServiceException, RemoteException
	{
//		OMQConnection con = new OMQConnectionSOAP(omqUser,omqPassword,omqSOAPServer,new OMQQueueManager(omqQueueManager));
		OMQConnection con = OMQConnectionFactory.getConnection(omqUser,omqPassword,new OMQQueueManager(omqQueueManager));
		int rc = con.checkConnection(new OMQQueue(omqQueue));
		OMQLogger.getInstance().info("con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription());
		assertEquals("check connection failed on error code "+rc+" error description "+con.getLastErrorDescription(),0,rc);
	}
	// ----------------------------------------------------------
	// test case - testing order of username, email parameters...
	// ----------------------------------------------------------
	public void testParametersOrder() throws ServiceException, RemoteException
	{
		OMQConnectionTestObject con = new OMQConnectionTestObject(omqUser,omqPassword,omqSOAPServer,new OMQQueueManager(omqQueueManager));
		int rc = con.checkConnection(new OMQQueue(omqQueue));
		// this test is only relevant if RC=0
		OMQLogger.getInstance().info("con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription());
		if (rc==0)
		{
			assertEquals("UserName sent not equal to UserName returned from SOAP request ",omqUser,con.getWOoutput().getOnlinemq().getAuthentication().getLogin());
			assertEquals("Queue Manager sent not equal to Queue Manager returned from SOAP request ",omqQueueManager,con.getWOoutput().getOnlinemq().getQueue_manager().getName());
			assertEquals("Queue Name sent not equal to Queue Name returned from SOAP request ",omqQueue,con.getWOoutput().getOnlinemq().getQueue_manager().getQueue_definition().getName());
//			assertEquals("Email sent not equal to Email returned from SOAP request ",omqEmail,con.getWOoutput().getOnlinemq().getAuthentication().getEmail());
		}
	}

	// ----------------------------------------------------------
	// test case - test successfully expected connection
	// ----------------------------------------------------------
	public void testConnectionError101_User_Not_Exists() throws ServiceException, RemoteException
	{
		OMQConnection con = OMQConnectionFactory.getConnection(invalidName,omqPassword,omqSOAPServer, new OMQQueueManager(omqQueueManager));
		int rc = con.checkConnection(new OMQQueue(omqQueue));
		OMQLogger.getInstance().info("con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription());
		assertEquals("invalid username - expected rc 101 - got error description "+con.getLastErrorDescription(),101,rc);	
	}
	public void testConnectionError101_Wrong_Password() throws ServiceException, RemoteException
	{
		OMQConnection con = OMQConnectionFactory.getConnection(omqUser,invalidName,omqSOAPServer, new OMQQueueManager(omqQueueManager));
		int rc = con.checkConnection(new OMQQueue(omqQueue));
		OMQLogger.getInstance().info("con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription());
		assertEquals("invalid username - expected rc 101 - got error description "+con.getLastErrorDescription(),101,rc);	
	}
	public void testConnectionError_Queue_Manager_Not_Exists() throws ServiceException, RemoteException
	{
		OMQConnection con = OMQConnectionFactory.getConnection(omqUser,omqPassword,omqSOAPServer, new OMQQueueManager(invalidName));
		int rc = con.checkConnection(new OMQQueue(omqQueue));
		OMQLogger.getInstance().info("con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription());
		assertEquals("invalid queue manager - expected rc 203 - got error description "+con.getLastErrorDescription(),203,rc);	
	}
	public void testConnectionError_Queue_Not_Exists() throws ServiceException, RemoteException
	{
		OMQConnection con = OMQConnectionFactory.getConnection(omqUser,omqPassword,omqSOAPServer, new OMQQueueManager(omqQueueManager));
		int rc = con.checkConnection(new OMQQueue(invalidName));
		OMQLogger.getInstance().info("con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription());
		assertEquals("invalid queue - expected rc 201 - got error description "+con.getLastErrorDescription(),201,rc);	
	}	
	public void testConnectionError_Queue_Manager_Name_Too_Long() throws ServiceException, RemoteException
	{
		OMQConnection con = OMQConnectionFactory.getConnection(omqUser,omqPassword,omqSOAPServer, new OMQQueueManager(invalidLongName21Chars));
		int rc = con.checkConnection(new OMQQueue(omqQueue));
		OMQLogger.getInstance().info("con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription());
		assertEquals("invalid queue manager - expected rc 203 - got error description "+con.getLastErrorDescription(),203,rc);	
	}
	public void testConnectionError_Queue_Name_Too_Long() throws ServiceException, RemoteException
	{		
		OMQConnection con = OMQConnectionFactory.getConnection(omqUser,omqPassword,omqSOAPServer, new OMQQueueManager(omqQueueManager));
		int rc = con.checkConnection(new OMQQueue(invalidLongName21Chars));
		OMQLogger.getInstance().info("con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription());
		assertEquals("invalid queue - expected rc 201 - got error description "+con.getLastErrorDescription(),201,rc);	
	}	
	
	// ----------------------------------------------------------
	// test case - send string message
	// ----------------------------------------------------------
	public void testSend_String_Message_Success() throws ServiceException, IOException, ClassNotFoundException
	{
		OMQLogger.getInstance().info("Test Send message");		
		OMQLogger.getInstance().info("-----------------------------------------------");		
		String stringSent = "hello world";
		sendMessage(stringSent);
	}
	
	// ----------------------------------------------------------
	// test case - peek string message (expect rc=0)
	// ----------------------------------------------------------
	public void testPeek_String_Message_Success() throws ServiceException, IOException, ClassNotFoundException
	{
		// sending dummy message to make sure the queue won't be empty
		sendMessage("dummy message");
		// peeking message
		OMQMessage peekedMessage = peekMessage(0);
		String stringReceived = (String)peekedMessage.getMsgBodyAsObject();
		OMQLogger.getInstance().info("string peeked : "+stringReceived);
	}
	
	// ----------------------------------------------------------
	// test case - receive string message (expect rc=0)
	// ----------------------------------------------------------
	public void testReceive_String_Message_Success() throws ServiceException, IOException, ClassNotFoundException
	{
		// sending dummy message to make sure the queue won't be empty
		sendMessage("dummy message");
		// peeking message
		OMQMessage receivedMessage = receiveMessage(0);
		String stringReceived = (String)receivedMessage.getMsgBodyAsObject();
		OMQLogger.getInstance().info("string received : "+stringReceived);
	}
	
	// ----------------------------------------------------------
	// test case - send 10 messages
	// ----------------------------------------------------------
	public void testSend_10_String_Message_Success() throws ServiceException, IOException, ClassNotFoundException
	{
		OMQLogger.getInstance().info("Test Send 10 messages");		
		OMQLogger.getInstance().info("-----------------------------------------------");
		for (int i=0; i<10; i++)
		{
			String stringSent = "hello world #"+(i+1);
			sendMessage(stringSent);
		}
	}
	// ----------------------------------------------------------
	// test case - receive string message (expect rc=313)
	// ----------------------------------------------------------
	public void testPeek_String_Message_313() throws ServiceException, IOException, ClassNotFoundException
	{
		sendMessage("dummy message1");
		sendMessage("dummy message2");
		// sending dummy message to make sure the queue won't be empty
		clearMessages();
		// peeking message
		if (peekMessage(0) == null)
			assertTrue(true);
		else
			assertTrue(false);
	}	
	// ----------------------------------------------------------
	// test case - receive string message (expect rc=313)
	// ----------------------------------------------------------
	public void testReceive_String_Message_313() throws ServiceException, IOException, ClassNotFoundException
	{
		// sending dummy message to make sure the queue won't be empty
		clearMessages();
		// receiving message
		if (receiveMessage(0) == null)
			assertTrue(true);
		else
			assertTrue(false);
	}

	// ----------------------------------------------------------
	// test case - test that the send item is identical to the received item
	// first we clean the queue in a loop of receive (also test receive and error code - no more messages on queue)
	// then we send a text message and receive it and compare the message and message id's 
	// ----------------------------------------------------------
	public void testClean_Send_Receive_Compare_Message() throws ServiceException, IOException, ClassNotFoundException
	{
		int currMessagesOnLoop=1;
		boolean OMQfailure=false;
		String errorMsg="";
		OMQLogger.getInstance().info("Test Send and Receive message");		
		OMQLogger.getInstance().info("-----------------------------------------------");		
		OMQConnection con = OMQConnectionFactory.getConnection(omqUser,omqPassword,omqSOAPServer, new OMQQueueManager(omqQueueManager));
		OMQSession sess = con.createSession(false);
			
		// cleaning all messages from queue (receive them in loop)
		OMQLogger.getInstance().info("about to receive all messages from queue");		
		OMQMessage msgReceived = sess.receiveMessage(new OMQQueue(omqQueue));
		OMQLogger.getInstance().info("con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription());
		while (sess.getLastErrorCode() == 0 && currMessagesOnLoop<maxMessagesOnLoop)
		{
			OMQLogger.getInstance().info("message #"+currMessagesOnLoop+" receive succesfully, msgid = "+sess.getLastMessageID());		
			OMQLogger.getInstance().info("More message on queue, looping till it's empty");		
			msgReceived = sess.receiveMessage(new OMQQueue(omqQueue));
			OMQLogger.getInstance().info("con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription());
			currMessagesOnLoop++;
		}
		if (sess.getLastErrorCode() != 313)
		{
			errorMsg = "failure on receive - con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription();
			OMQfailure=true;
		}
		else
		{
			OMQLogger.getInstance().info("no more message on queue, it's empty now (313)");		
		}
		if (!OMQfailure)
		{
			//send one message
			
		
			if (sess.getLastErrorCode() != 0)
			{
				errorMsg = "failure on receive - con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription();
				OMQfailure=true;
			}
		}
		if (!OMQfailure)
		{
			//receive one message
			OMQMessage msgReceived2 = sess.receiveMessage(new OMQQueue(omqQueue));
			
			if (sess.getLastErrorCode() != 0)
			{
				errorMsg = "failure on receive - con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription();
				OMQfailure=true;
			}
		}

		if (!OMQfailure)
		{
			//compare messages content and message-id
//			if (messageid == messageid)
//				if (rc == rc)
			// compare message content
		}
		

	
							
		//assertEquals("string sent : "+stringSent+" not equal to string received : "+stringReceived, true,stringReceived.equals(stringSent));

	}
	// ----------------------------------------------------------
	// test case - test that the send FILE is identical to the received FILE
	// first we clean the queue in a loop of receive (also test receive and error code - no more messages on queue)
	// then we send the FILE and receive it
	// ----------------------------------------------------------
	public void testSend_Receive_Compare_File() throws ServiceException, IOException, ClassNotFoundException
	{
		
	}
	// -------------------------------------------
	// setup environment
	// -------------------------------------------
	public void initEnv(String [] args) throws OMQPropertiesReaderException
	{
		final String defaultPropertiesFile = "omq.properties";
		String propertiesFile = defaultPropertiesFile;
		boolean success=true;
		
		OMQLogger.getInstance().info("##########################################################################");
		OMQLogger.getInstance().info("# OMQ JUnit started at "+(OMQUtils.time("yyyy.MM.dd 'at' hh:mm:ss")));		
		OMQLogger.getInstance().info("##########################################################################");

		if (args.length>0)
		{
			if (args[0].compareToIgnoreCase("-classpath")!= 0)
			{
				propertiesFile = args[0];
				OMQLogger.getInstance().info("using given properties file named "+propertiesFile);
			}
		}
		else
		{
			OMQLogger.getInstance().info("Using default properties file named "+propertiesFile+", you can pass a properties file name as a parameter to this java program");
		}
		propertiesReader = OMQPropertiesReader.createOMQPropertiesReader(propertiesFile);

		OMQLogger.getInstance().info("about to read properties from "+propertiesReader.getPropertiesFileName());
		
		// getting parameters from property file

		omqUser = propertiesReader.getProperty("omq.ml.user");
		omqPassword = propertiesReader.getProperty("omq.ml.pwd");
		omqEmail = propertiesReader.getProperty("omq.ml.email");
		omqQueueManager = propertiesReader.getProperty("omq.ml.queueMgr");
		omqQueue = propertiesReader.getProperty("omq.ml.queue");
		omqSOAPServer = propertiesReader.getProperty("omq.ml.ws.addr");
		
		OMQLogger.getInstance().info("-----------------------------------------------");
		OMQLogger.getInstance().info("using user named          : "+omqUser);
		OMQLogger.getInstance().info("using email               : "+omqEmail);
		OMQLogger.getInstance().info("using SOAP server named   : "+omqSOAPServer);
		OMQLogger.getInstance().info("using queue manager named : "+omqQueueManager);
		OMQLogger.getInstance().info("using queue named         : "+omqQueue);
		OMQLogger.getInstance().info("-----------------------------------------------");

	}
	
	// sendMessage - expect rc 0
	private String sendMessage(String stringSent) throws ServiceException, IOException
	{
		OMQConnection con = OMQConnectionFactory.getConnection(omqUser,omqPassword,omqSOAPServer, new OMQQueueManager(omqQueueManager));
		OMQSession sess = con.createSession(false);
		
		OMQMessage msgSent = new OMQMessage(stringSent);
		OMQLogger.getInstance().info("about to send text message : "+stringSent);	
		
		int rc = sess.sendMessage(new OMQQueue(omqQueue), msgSent);
		
		OMQLogger.getInstance().info("con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription());
		if (sess.getLastErrorCode() == 0)
		{
			OMQLogger.getInstance().info("message sent succesfully, msgid = "+sess.getLastMessageID());		
		}
		assertEquals("send message failed on error code "+rc+" error description "+con.getLastErrorDescription(),0,rc);
		return sess.getLastMessageID();
	}
	
	// receiveMessage
	private OMQMessage receiveMessage(int expectedRc) throws ServiceException, IOException
	{
		OMQConnection con = OMQConnectionFactory.getConnection(omqUser,omqPassword,omqSOAPServer, new OMQQueueManager(omqQueueManager));
		OMQSession sess = con.createSession(false);
			
		OMQLogger.getInstance().info("about to receive message");		
		OMQMessage msgReceived = sess.receiveMessage(new OMQQueue(omqQueue));
		OMQLogger.getInstance().info("con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription());

		if (sess.getLastErrorCode() == 0)
		{
			OMQLogger.getInstance().info("receive succesfully, msgid = "+sess.getLastMessageID());
		}
		else if (sess.getLastErrorCode() == 313)
		{
			OMQLogger.getInstance().info("receive succesfully, queue is empty");
			return null;
		}
		assertEquals("receive message failed on error code: "+sess.getLastErrorCode()+" error description: "+con.getLastErrorDescription(),expectedRc,sess.getLastErrorCode());
		return msgReceived;
	}
	
	// peekMessage
	private OMQMessage peekMessage(int expectedRc) throws ServiceException, IOException
	{
		OMQConnection con = OMQConnectionFactory.getConnection(omqUser,omqPassword,omqSOAPServer, new OMQQueueManager(omqQueueManager));
		OMQSession sess = con.createSession(false);
			
		OMQLogger.getInstance().info("about to peek message");		
		OMQMessage msgReceived = sess.peekMessage(new OMQQueue(omqQueue));
		OMQLogger.getInstance().info("con.getLastErrorCode()="+con.getLastErrorCode()+", con.getLastErrorDescription()="+con.getLastErrorDescription());

		if (sess.getLastErrorCode() == 0)
		{
			OMQLogger.getInstance().info("peek succesfully, msgid = "+sess.getLastMessageID());
		}
		else if (sess.getLastErrorCode() == 313)
		{
			OMQLogger.getInstance().info("peek succesfully, queue is empty");
			return null;
		}
		assertEquals("peek message failed on error code: "+sess.getLastErrorCode()+" error description: "+con.getLastErrorDescription(),expectedRc,sess.getLastErrorCode());
		return msgReceived;
	}

	private void clearMessages() throws ServiceException, IOException
	{
		OMQLogger.getInstance().info("Cleaning messages from queue");
		int currMessagesOnLoop=1;
		while (receiveMessage(0) != null);
	
	}
}
